package com.zxjbyte.yiyi.module.system.service.auth.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.util.IdUtil;
import com.zxjbyte.yiyi.module.system.context.properties.CaptchaProperties;
import com.zxjbyte.yiyi.module.system.domain.response.auth.CaptchaResponse;
import com.zxjbyte.yiyi.module.system.service.auth.ICaptchaService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 基于HttpSession的方式：
 * 在单体应用或需要基于用户会话状态的场景下，使用Session存储验证码是一个简单有效的方式
 *
 * 可改造成基于Redis等存储的方式
 *
 * @Author zhangxingjia
 * @Date 2024/8/13 17:05
 * @Version: 1.0
 */
@Service
public class CaptchaServiceImpl implements ICaptchaService {

    private static final String SESSION_CAPTCHA_CODE = "captchaCode";
    private static final String SESSION_CAPTCHA_UUID = "captchaUUID";

    @Resource
    private CaptchaProperties properties;
    @Resource
    private CodeGenerator codeGenerator;

    @Override
    public CaptchaResponse generateCaptcha(HttpSession session) {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(properties.getWidth(), properties.getHeight(), codeGenerator, properties.getLineCount());
        String uuid = IdUtil.fastUUID();
        // 将验证码存储在Session中
        session.setAttribute(SESSION_CAPTCHA_CODE, lineCaptcha.getCode());
        session.setAttribute(SESSION_CAPTCHA_UUID, uuid);
        CaptchaResponse response = new CaptchaResponse();
        response.setUuid(uuid);
        response.setCaptchaImage(lineCaptcha.getImageBase64Data());
        return response;
    }

    @Override
    public boolean verify(HttpServletRequest request, String uuid, String code) {
        HttpSession session = request.getSession(false);
        if(session == null){
            return false;
        }
        String sessionUUID = (String) session.getAttribute(SESSION_CAPTCHA_UUID);
        String storedCode = (String) session.getAttribute(SESSION_CAPTCHA_CODE);

        if (sessionUUID != null && sessionUUID.equals(uuid) && codeGenerator.verify(storedCode, code)) {
            // 验证成功后清除Session中的验证码
            session.removeAttribute(SESSION_CAPTCHA_UUID);
            session.removeAttribute(SESSION_CAPTCHA_CODE);
            return true;
        }
        return false;
    }
}
